<template>
  <div
    :class="animate"
    :style="{ height: height, width: width, overflowY: 'hidden' }"
    :id="chartOption.bindingDiv"
     @mouseenter="visible" @mouseleave="invisible"
    ref="text"
  >
    <template v-for="(item, rowindex) in rows">
      <div :style="rowStyle" :key="rowindex">
        <!-- <div :style="cardTop"></div> -->
        <template v-for="(col, colindex) in item">
          <div :style="divStyle" :key="colindex">
            <div :style="headStyle">
              <img :src="col.head.headImg" :style="headImgStyle" />
              <img :src="tipSrc" :style="tipImgStyle(col)" />
              <div :style="tipTextStyle">
                <span>{{ col.head.tipText }}</span>
              </div>
            </div>

            <div :style="nameStyle">
              {{ col.name }}
            </div>
            <div
              :style="{
                display: 'flex',
                flexDirection: 'column',
                position: 'relative',
                height: chartOption.infoItem.height + '%'
              }"
            >
              <template v-for="(info, infoindex) in col.infoItem">
                <div :style="itemStyle(col)" :key="infoindex">
                  <div
                    :style="{
                      marginLeft: chartOption.infoItem.textMarginLeft + '%',
                      marginTop: chartOption.infoItem.textMarginTop + '%'
                    }"
                  >
                    {{ info.label }}
                  </div>
                  <div
                    :style="{
                      marginRight: '3%',
                      marginTop: chartOption.infoItem.textMarginTop + '%'
                    }"
                  >
                    {{ info.value }}
                  </div>
                </div>
              </template>
            </div>
            <div :style="detailStyle">
              <template v-for="(detail, detailindex) in col.detailItem">
                <div
                  :style="detailInfoStyle(col)"
                  :key="detailindex"
                  @click="fieldClick(col, detail)"
                  class="detail"
                >
                  <div
                    :style="{
                      marginTop: chartOption.detailItem.textMarginTop + '%'
                    }"
                  >
                    <a v-if="typeof detail == 'string'">{{ detail }}</a>
                    <a v-else :href="getHref(detail)" target="_blank">{{
                      detail.label
                    }}</a>
                  </div>
                </div>
              </template>
            </div>
          </div>
        </template>
      </div>
    </template>
  </div>
</template>

<script>
import resize from "@/views/dashboard/mixins/resize";
import VueEvent from "@/views/tool/datav/VueEvent";
import "../../animate/animate.css";
import { getFormsource } from "@/api/tool/datav/formsource";
import { parseQueryString, fIsUrL } from "../../util/urlUtil";
import { chartApiBar, remoteChartApi } from "@/api/tool/datav/chartApi";
import { websocketCommand } from "../../util/websocket.js";
import { bindChart } from "../../util/LinkageChart";

const animationDuration = 6000;

export default {
  mixins: [resize],
  props: {
    className: {
      type: String,
      default: "chart"
    },
    width: {
      type: String,
      default: "100%"
    },
    height: {
      type: String,
      default: "100%"
    },
    chartOption: {
      type: Object
    },
    drawingList: {
      type: Array
    }
  },
  data() {
    return {
      dataOption: JSON.parse(JSON.stringify(this.chartOption)),
      rows: [],
      tipText: "", //提示框文字
      name: "", //名称
      cardheight: "", //每个卡片高度占比
      cardwidth: "", //每个卡片宽度占比
      tipSrc: require("../../../../../assets/image/tip.png"),
      timer: "",
      wsObj: null,
      wsFlag: false,
      wsTimer: "",
      wsValue: null,
      animate: this.className
    };
  },
  watch: {
    width() {},
    height() {},
    chartOption: {
      deep: true,
      handler(newVal) {
        this.setOptions(JSON.parse(JSON.stringify(newVal)));
      }
    },
    "chartOption.timeout": {
      handler() {
        this.initChart();
      }
    },
    "chartOption.head.tipImg.src": {
      handler(value) {
        this.tipSrc = value;
      }
    },
    "chartOption.dataSourceType": {
      handler(value) {
        //切换数据源重新连接
        if (value !== "websocket") {
          this.wsFlag = false;
          //每次切换数据源恢复原来动画
          this.animate = this.className;
        }
        if (value !== "url") {
          clearTimeout(this.timer);
        } 
      }
    },
    "chartOption.interfaceKey": {
      handler(newValue, oldValue) {
        //初始化不创建连接，改变接口地址重新创建
        if (oldValue !== undefined && oldValue != "") {
          this.wsValue = null;
          this.closeWs();
          this.createWs();
          this.animate = this.className;
        }
      }
    },
    wsFlag: {
      handler(value) {
        if (!value) {
          this.wsValue = null;
          this.closeWs();
        }
      }
    },
    className: {
      handler(value) {
        this.animate = value;
      }
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.initChart();
    });
  },
  beforeDestroy() {
    clearTimeout(this.timer);
    if (this.wsFlag) {
      this.closeWs();
    }
  },
  computed: {
    rowStyle() {
      let style = {
        width: "100%",
        display: "flex",
        flexDirection: "row",
        height: "100%",
        marginTop: this.chartOption.marginTop + "%"
      };
      return style;
    },
    cardTop() {
      const style = { height: this.chartOption.marginTop + "%" };
      return style;
    },
    divStyle() {
      const style = {
        width: this.cardwidth + "%",
        height: "100%",
        position: "relative",
        marginLeft: this.chartOption.marginLeft + "%"
      };
      return style;
    },
    headStyle() {
      const style = {
        width: "100%",
        height: this.chartOption.head.height + "%",
        marginTop: this.chartOption.head.marginTop + "%",
        position: "relative"
      };
      return style;
    },
    headImgStyle() {
      const style = {
        width: this.chartOption.head.headImg.width + "%",
        height: this.chartOption.head.headImg.height + "%",
        marginLeft: this.chartOption.head.headImg.marginLeft + "%",
        position: "absolute"
      };
      return style;
    },
    tipTextStyle() {
      const style = {
        color: this.chartOption.head.tipText.fontColor,
        fontSize: this.chartOption.head.tipText.fontSize + "px",
        fontFamily: this.chartOption.head.tipText.fontFamily,
        fontWeight: this.chartOption.head.tipText.fontWeight,
        letterSpacing: this.chartOption.head.tipText.letterSpacing + "px",
        marginLeft: this.chartOption.head.tipText.marginLeft + "%",
        marginTop: this.chartOption.head.tipText.marginTop + "%",
        position: "absolute"
      };
      return style;
    },
    nameStyle() {
      const style = {
        color: this.chartOption.name.fontColor,
        fontSize: this.chartOption.name.fontSize + "px",
        fontFamily: this.chartOption.name.fontFamily,
        fontWeight: this.chartOption.name.fontWeight,
        letterSpacing: this.chartOption.name.letterSpacing + "px",
        marginLeft: this.chartOption.name.marginLeft + "%",
        marginTop: this.chartOption.name.marginTop + "%",
        marginBottom: this.chartOption.name.marginBottom + "%",
        position: "relative"
      };
      return style;
    },
    detailStyle() {
      const style = {
        display: "flex",
        flexDirection: "column",
        position: "relative",
        color: this.chartOption.detailItem.fontColor,
        fontSize: this.chartOption.detailItem.fontSize + "px",
        fontFamily: this.chartOption.detailItem.fontFamily,
        fontWeight: this.chartOption.detailItem.fontWeight,
        letterSpacing: this.chartOption.detailItem.letterSpacing + "px",
        marginLeft: "3%",
        width: "94%",
        height: this.chartOption.detailItem.height + "%"
      };

      return style;
    }
  },
  methods: {
    initChart() {
      //判断是否开启定时器，当是访问url接口时候并且timeout不为0时候开启定时器
      if (this.timer != "") {
        clearTimeout(this.timer);
      }
      if (
        (this.chartOption.dataSourceType == 'url' || this.chartOption.dataSourceType == 'database') &&
        this.chartOption.timeout > 0
      ) {
        let timerTask = () => {
          this.setOptions(JSON.parse(JSON.stringify(this.chartOption)));
          this.timer = setTimeout(() => {
            timerTask();
          }, this.chartOption.timeout);
        };

        timerTask();
      }else{
        this.setOptions(JSON.parse(JSON.stringify(this.chartOption)));
      }
    },
    setOptions: async function(dataOption) {
      //console.log("=>",dataOption)

      //初始化数据
      //如果不是静态数据就调用接口给staticDataValue赋值
      if (dataOption.dataSourceType == "url") {
        let paramJson = parseQueryString(dataOption.requestParameters);

        let interfaceURL = dataOption.interfaceURL;

        dataOption.staticDataValue = await chartApiBar(
          dataOption.requestMethod,
          interfaceURL,
          paramJson,
          dataOption.token
        );
        this.$set(
          this.dataOption,
          "staticDataValue",
          dataOption.staticDataValue
        );
      } else if (dataOption.dataSourceType == "database") {
      } else if (dataOption.dataSourceType == "form") {
      } else if (dataOption.dataSourceType == "websocket") {
        if (
          dataOption.interfaceKey != undefined &&
          dataOption.interfaceKey != ""
        ) {
          if (!this.wsFlag) {
            this.wsFlag = true;
            this.wsValue = null;
            this.createWs();
          }
          if (this.wsValue != null) {
            dataOption.staticDataValue = this.wsValue;
          }
        }
      }
      this.rows = this.getRows(dataOption.staticDataValue);
      //数据处理
       if(dataOption.customData != undefined && dataOption.customData != ""){
          this.$nextTick(() => {
              
              try {
                dataOption.staticDataValue = (
                  //里面为要处理的代码块 
                  eval(dataOption.customData) 
                
                )(
                  dataOption.staticDataValue,
                  this.$refs.text
                );
                this.rows = this.getRows(dataOption.staticDataValue);
              } catch (error) {
                console.log(error)
              }
              
          })
       
       
       }
      //交互组件配置
       if(dataOption.interactData != undefined && dataOption.interactData != ""){
          this.$nextTick(() => {
              
              try {
                dataOption.staticDataValue = (
                  //里面为要处理的代码块 
                  eval(dataOption.interactData) 
                
                )(
                  dataOption.staticDataValue,
                  this.$refs.text
                );
                this.rows = this.getRows(dataOption.staticDataValue);
              } catch (error) {
                console.log(error)
              }
              
          })
       
       
       }      
    },
    getRows(staticDataValue) {
      //根据列数计算数据的行数，并按顺序将数据构造成按指定行、列分隔的数组
      let results = [];
      //列数，判断列数不能大于数据数组的总长度
      let colsNum = this.chartOption.staticDataValue.length;
      if (this.chartOption.numOfCol < this.chartOption.staticDataValue.length) {
        colsNum = this.chartOption.numOfCol;
      }
      let col = 0; //卡片行数
      for (let i = 0; i < staticDataValue.length; ) {
        let rows = [];
        for (let j = 0; j < colsNum && i < staticDataValue.length; j++) {
          //每行数据
          rows.push(staticDataValue[i]);
          i++;
        }
        results.push(rows);
        col++;
      }
      //每个卡片宽度占比
      this.cardwidth =
        (100 - this.chartOption.marginLeft * this.chartOption.numOfCol) /
        this.chartOption.numOfCol;
      //每个卡片高度占比
      this.cardheight = (100 - col * this.chartOption.marginTop) / col;

      return results;
    },
    visible:function(){
      
      let style = document.getElementById(this.chartOption.bindingDiv).style;
      style.overflowY = 'auto'
      
    },
    invisible:function(){
      let style = document.getElementById(this.chartOption.bindingDiv).style;
      style.overflowY = 'hidden'
      
    },
    //信息航样式
    itemStyle(card) {
      //计算平均每行高度
      const itemRows = card.infoItem.length;

      const height =
        (100 - this.chartOption.infoItem.marginTop * itemRows) / itemRows;

      const style = {
        display: "flex",
        justifyContent: "space-between",
        color: this.chartOption.infoItem.fontColor,
        fontSize: this.chartOption.infoItem.fontSize + "px",
        fontFamily: this.chartOption.infoItem.fontFamily,
        fontWeight: this.chartOption.infoItem.fontWeight,
        letterSpacing: this.chartOption.infoItem.letterSpacing + "px",
        marginLeft: "3%",
        marginTop: this.chartOption.infoItem.marginTop + "%",
        width: "94%",
        height: height + "%"
      };
      if (this.chartOption.infoItem.background == "color") {
        style.backgroundColor = this.chartOption.infoItem.backgroundColor;
      } else {
        style.backgroundImage = `url(${
          this.chartOption.infoItem.backgroundImg
        }) `;
        style.backgroundSize = "100% 100%";
        style.backgroundRepeat = "no-repeat";
      }
      return style;
    },
    detailInfoStyle(card) {
      //计算平均每行高度
      const itemRows = card.detailItem.length;

      const height =
        (100 - this.chartOption.detailItem.marginTop * itemRows) / itemRows;

      const style = {
        textAlign: "center",
        marginTop: this.chartOption.detailItem.marginTop + "%",
        height: height + "%"
      };
      if (this.chartOption.detailItem.background == "color") {
        style.backgroundColor = this.chartOption.detailItem.backgroundColor;
      } else {
        style.backgroundImage = `url(${
          this.chartOption.detailItem.backgroundImg
        })`;
        style.backgroundSize = "100% 100%";
        style.backgroundRepeat = "no-repeat";
      }
      return style;
    },
    tipImgStyle(col) {
      const style = {
        width: this.chartOption.head.tipImg.width + "%",
        height: this.chartOption.head.tipImg.height + "%",
        marginLeft: this.chartOption.head.tipImg.marginLeft + "%",
        marginTop: this.chartOption.head.tipImg.marginTop + "%",
        position: "absolute"
      };
      //判断是否和提示框文字同步显示
      if (this.chartOption.head.tipImg.sync) {
        if (col.head.tipText == "") {
          style.display = "none";
        } else {
          style.display = "show";
        }
      } else {
        style.display = this.chartOption.head.tipImg.show;
      }

      return style;
    },
    getHref(detail) {
      if (
        typeof detail == "object" &&
        detail.address != undefined &&
        detail.address != ""
      ) {
        return detail.address;
      }
    },
    fieldClick(col, detail) {
      // 获取联动图表
      if (this.chartOption.isLink == true) {
        if (this.chartOption.linkageRows != undefined) {
          this.chartOption.staticDataValue.forEach(card => {
            //根据id获取点击的具体卡片
            if (card.id == col.id) {
              //获取点击的具体详细按钮
              let linkageTag = this.chartOption.linkageRows.filter(function(
                item
              ) {
                return item.field == detail;
              })[0];

              //判断按钮名称相符并且有参数名称
              if (linkageTag != undefined && linkageTag.paramName != "") {
                let bindList = linkageTag.bindingChart;

                //判断已绑定图表列表
                if (bindList.length > 0) {
                  bindChart(
                    linkageTag.paramName,
                    JSON.stringify(col),
                    bindList,
                    this.drawingList
                  );
                }
              }
            }
          });
        }
      }
      //开启图表下钻
      else if (this.chartOption.isDrillDown == true) {
        if (this.chartOption.drillRows != undefined) {
          this.chartOption.staticDataValue.forEach(card => {
            //根据id获取点击的具体卡片
            if (card.id == col.id) {
              //获取联动图表
              let drillTag = this.chartOption.drillRows.filter(function(item) {
                return item.field == detail;
              })[0];

              if (drillTag != undefined && drillTag.bindingChart != "") {
                let num = 0;
                for (let i = 0; i < this.chartOption.drillRows.length; i++) {
                  if (this.chartOption.drillRows[i].field == drillTag.field) {
                    num = i;
                  }
                }

                //获取绑定的图表
                let drillDownChartOption = drillTag.drillDownChartOption;

                drillDownChartOption.drillBgColor = drillTag.drillBgColor;

                if (
                  drillDownChartOption != undefined &&
                  drillDownChartOption != null
                ) {
                  //判断是否有参数传递
                  if (
                    drillTag.paramName != null &&
                    drillTag.paramName != "" &&
                    drillTag.paramName != undefined
                  ) {
                    this.$set(
                      this.chartOption.drillRows[num].drillDownChartOption
                        .chartOption,
                      "requestParameters",
                      drillTag.paramName + "=" + JSON.stringify(col)
                    );
                    drillDownChartOption.chartOption.requestParameters =
                      drillTag.paramName + "=" + JSON.stringify(col);
                  } else {
                    this.$set(
                      this.chartOption.drillRows[num].drillDownChartOption
                        .chartOption,
                      "requestParameters",
                      ""
                    );
                    drillDownChartOption.chartOption.requestParameters = "";
                  }

                  //发送下钻消息
                  VueEvent.$emit("drill_down_msg", drillDownChartOption);
                }
              }
            }
          });
        }
      }
      //开启图表远程控制
      if (
        this.chartOption.isRemote == true &&
        this.chartOption.remoteRows != undefined
      ) {
        this.chartOption.staticDataValue.forEach(card => {
          //根据id获取点击的具体卡片
          if (card.id == col.id) {
            //获取点击的按钮
            let remoteTag = this.chartOption.remoteRows.filter(function(item) {
              return item.field == detail;
            })[0];

            if (
              remoteTag != undefined &&
              remoteTag.interfaceKey != undefined &&
              remoteTag.interfaceKey != "" &&
              remoteTag.paramName != ""
            ) {
              let remoteData = {};
              //创建ws接口地址数组
              let interfaceArr = new Array();
              let interfaceObj = {
                interfaceKey: remoteTag.interfaceKey,
                interfaceName: remoteTag.interfaceName,
                interfaceUrl: remoteTag.interfaceUrl
              };
              interfaceArr.push(interfaceObj);
              //ws接口参数
              remoteData.interface = interfaceArr;

              //查询参数对象
              let queryObj = {};
              queryObj[remoteTag.paramName] = JSON.stringify(col);
              remoteData.query = queryObj;

              // //调用接口
              remoteChartApi(remoteData);
            }
          }
        });
      }
    },
    //  ws连接成功，后台返回的ws数据
    receiveMsg(e) {
      if (e.action == "chat") {
        // console.log('服务端推送',e);
        this.wsValue = JSON.parse(e.result);
        this.setOptions(JSON.parse(JSON.stringify(this.chartOption)));
      }
    },
    // 建立连接、发起ws请求，以心跳方式，向服务端发送数据
    createWs() {
      this.wsObj = new WebSocket(process.env.VUE_APP_WEBSOCKET);
      // 若为对象类型，以回调方式发送
      websocketCommand(
        this.wsObj,
        "create",
        5000,
        this.chartOption.interfaceKey,
        this.sendHeartBeat,
        this.receiveMsg,
        this.reconnectWs,
        this.wsWarning
      );
    },
    // 断网重连，需要处理的逻辑
    reconnectWs() {
      if (this.wsObj) {
        console.log("%c websocket_reconnect", "color:blue");
        this.createWs();
      }
    },
    // 以回调方式向服务端发送(对象类型的)心跳
    sendHeartBeat() {
      if (this.wsTimer != "") {
        clearTimeout(this.wsTimer);
      }

      let wsTimerTask = () => {
        console.log("发送心跳", "ping");
        let obj = { action: "keep", key: this.chartOption.interfaceKey };
        this.wsObj.send(JSON.stringify(obj));
        this.wsTimer = setTimeout(() => {
          wsTimerTask();
        }, parseInt(process.env.VUE_APP_WEBSOCKET_TIMEOUT));
        this.wsWarning();
      };

      wsTimerTask();
    },
    wsWarning() {
      //如果断开连接则显示组件警告动画并清除计数器
      if (this.wsObj.readyState == 3) {
        this.animate = "warning";
        clearTimeout(this.wsTimer);
      }
    },
    closeWs() {
      clearTimeout(this.wsTimer);
      websocketCommand(
        this.wsObj,
        "close",
        5000,
        this.chartOption.interfaceKey,
        this.sendHeartBeat,
        this.receiveMsg,
        this.reconnectWs,
        this.wsWarning
      );
      this.wsObj = null;
    }
  }
};
</script>
<style ang="scss" scoped>
.detail:hover {
  cursor: default;
}
</style>